package com.spark.common.utils;

import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.util.CollectionUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 构建数据树
 *
 * @author LYCHEE
 * @date 2025/2/18 13:29
 */
@Data
@Accessors(chain = true)
public class TreeBuilderUtils {

    /**
     * 节点字段名称
     */
    private String nodeField = "id";

    /**
     * 父节点字段名称
     */
    private String parentNodeField = "pid";

    /**
     * 子节点字段名称
     */
    private String childrenNodeField = "children";

    /**
     * 使用默认的构造器进行构造,需保证实体类中必须包含 id、pid 和 children 三个字段，也可通过set方法设置字段名称
     */
    public TreeBuilderUtils() {

    }

    /**
     * 全参构造器
     *
     * @param nodeField         节点字段名称
     * @param parentNodeField   父节点字段名称
     * @param childrenNodeField 子节点字段名称
     */
    public TreeBuilderUtils(String nodeField, String parentNodeField, String childrenNodeField) {
        this.nodeField = nodeField;
        this.parentNodeField = parentNodeField;
        this.childrenNodeField = childrenNodeField;
    }

    /**
     * 构建数据树
     *
     * @param dataList 所有需要处理的数据
     * @return 数据树
     */
    public <T> List<T> buildTree(List<T> dataList) {
        // 获取所有顶层节点，即没有父节点的节点
        List<T> rootNodes = dataList.stream()
                .filter(node -> "0".equals(ReflectUtils.getField(node, parentNodeField, String.class)))
                .collect(Collectors.toList());
        // 没有父级节点，直接返回
        if (CollectionUtils.isEmpty(rootNodes)) {
            return dataList;
        }
        // 递归构建树
        for (T rootNode : rootNodes) {
            buildChildNodes(rootNode, dataList, false);
        }
        return rootNodes;
    }

    /**
     * 构建数据树,设置叶子节点
     *
     * @param dataList 所有需要处理的数据
     * @param isLeafFlag   是否设置叶子节点
     * @return 数据树
     */
    public <T> List<T> buildTree(List<T> dataList, boolean isLeafFlag) {
        // 获取所有顶层节点，即没有父节点的节点
        List<T> rootNodes = dataList.stream()
                .filter(node -> "0".equals(ReflectUtils.getField(node, parentNodeField, String.class)))
                .collect(Collectors.toList());
        // 没有父级节点，直接返回
        if (CollectionUtils.isEmpty(rootNodes)) {
            return dataList;
        }
        // 递归构建树
        for (T rootNode : rootNodes) {
            buildChildNodes(rootNode, dataList, isLeafFlag);
        }
        return rootNodes;
    }

    /**
     * 对树进行排序
     * @param nodeList 数节点list
     * @param fieldName 需要排序的属性
     * @param ascending true 升序 false 降序
     * @param <T> 类型
     */
    public static <T> void sortTreeNodes(List<T> nodeList, String fieldName, boolean ascending) {
        nodeList.sort(new Comparator<T>() {
            @Override
            public int compare(T node1, T node2) {
                // 使用反射获取字段的值
                Integer val1 = ReflectUtils.getField(node1, fieldName, Integer.class);
                Integer val2 = ReflectUtils.getField(node2, fieldName, Integer.class);
                if(!Objects.isNull(val1) && !Objects.isNull(val2)) {
                    if (ascending) {
                        return val1.compareTo(val2);
                    } else {
                        return val2.compareTo(val1);
                    }
                }
                return 0;
            }
        });
    }

    /**
     * 递归构建树
     *
     * @param parentNode 父级节点
     * @param dataList   所有的数据
     * @param isLeafFlag   是否设置叶子节点
     */
    private <T> void buildChildNodes(T parentNode, List<T> dataList, boolean isLeafFlag) {
        // 获取当前节点的子节点
        List<T> childNodes = dataList.stream()
                .filter(node -> ReflectUtils.getField(node, parentNodeField, String.class) != null
                        && Objects.equals(ReflectUtils.getField(node, parentNodeField, String.class)
                        , ReflectUtils.getField(parentNode, nodeField, String.class)))
                .collect(Collectors.toList());

        // 映射isLeaf字段,前端平台需要true或者false
        if (isLeafFlag){
            Boolean isLeaf = ReflectUtils.getField(parentNode, "isLeaf", Boolean.class);
            if (null != isLeaf) {
                ReflectUtils.setField(parentNode, "isLeaf", !isLeaf);
            }
        }

        // 递归构建子节点的子节点
        for (T childNode : childNodes) {
            buildChildNodes(childNode, dataList, isLeafFlag);
        }

        // 设置当前节点的子节点列表
        ReflectUtils.setField(parentNode, childrenNodeField, childNodes);
    }

}
